package com.qk.common.util;

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import com.qk.common.config.AliYunOSSProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author MrZhao
 * @created 2025-10-08 18:30
 * @description 阿里云OSS操作工具类
 *
 */
@Slf4j
@Component
public class AliYunOSSOperators {

    @Autowired
    private AliYunOSSProperties aliYunOSSProperties;



    //获取阿里云OSS客户端实例对象
    private OSS getOssClient() throws com.aliyuncs.exceptions.ClientException {
        // 从环境变量中获取访问凭证。运行本代码示例之前，请先配置环境变量
        EnvironmentVariableCredentialsProvider credentialsProvider =
                CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时，调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        // 显式声明使用 V4 签名算法
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        return OSSClientBuilder.create()
                .endpoint(aliYunOSSProperties.getEndpoint())
                .credentialsProvider(credentialsProvider)
                .region(aliYunOSSProperties.getRegion())
                .build();
    }


    public String upload(byte[] content, String objectName) {
        // 创建OSSClient实例
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = null;
        try {
            ossClient = OSSClientBuilder.create()
                    .endpoint(aliYunOSSProperties.getEndpoint())
                    .credentialsProvider(new EnvironmentVariableCredentialsProvider())
                    .clientConfiguration(clientBuilderConfiguration)
                    .region(aliYunOSSProperties.getRegion())
                    .build();
            // 创建PutObjectRequest对象
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliYunOSSProperties.getBucketName(), objectName, new ByteArrayInputStream(content));
            // 上传文件
            ossClient.putObject(putObjectRequest);

            // 返回文件访问URL
            return "https://" + aliYunOSSProperties.getBucketName() + "." + aliYunOSSProperties.getEndpoint().substring(8) + "/" + objectName;
        } catch (Exception e) {
            log.error("Caught an OSSException: " + e.getMessage());
            throw e;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }




    public List<String> getNames() throws com.aliyuncs.exceptions.ClientException {
        OSS ossClient = getOssClient();
        List<String> urls = new ArrayList<>();
        try {
            // 4. 列出文件
            ObjectListing objectListing = ossClient.listObjects(aliYunOSSProperties.getBucketName());
            for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                //过滤出所有大于当天0点时刻这段时间中更新的文件加入到集合中
                if (objectSummary.getLastModified().after(Date.from(
                        LocalDate.now()
                                .atStartOfDay()           // 转换为当天的开始时间 (00:00:00)
                                .atZone(ZoneId.systemDefault())  // 指定时区
                                .toInstant()               // 转换为Instant
                ))){
                    urls.add(objectSummary.getKey());
                }
            }

        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message:" + oe.getErrorMessage());
            log.error("Error Code:" + oe.getErrorCode());
            log.error("Request ID:" + oe.getRequestId());
            log.error("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message:" + ce.getMessage());
        } finally {
            if (Objects.nonNull(ossClient)) {
                ossClient.shutdown();
            }
            return urls;
        }
    }



    public void deleteFiles(List<String> urls) throws com.aliyuncs.exceptions.ClientException {
        //创建OSSClient实例
        OSS ossClient = getOssClient();

        try {
            // 删除文件。
            // 填写需要删除的多个文件完整路径。文件完整路径中不能包含Bucket名称。
            List<String> keys = new ArrayList<String>();

            for (String url : urls) {
                String objectKey = extractObjectKeyFromUrl(url, aliYunOSSProperties.getEndpoint(), aliYunOSSProperties.getBucketName());
                if (!Objects.isNull(objectKey))keys.add(objectKey);
            }
            if (keys.isEmpty()||keys.size()==0)return;
            DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(aliYunOSSProperties.getBucketName()).withKeys(keys).withEncodingType("url"));
            List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
            for(String obj : deletedObjects) {
                String deleteObj =  URLDecoder.decode(obj, StandardCharsets.UTF_8);
                log.info(deleteObj);
            }
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message:" + oe.getErrorMessage());
            log.error("Error Code:" + oe.getErrorCode());
            log.error("Request ID:" + oe.getRequestId());
            log.error("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message:" + ce.getMessage());
        } finally {
            if (Objects.nonNull(ossClient)) {
                ossClient.shutdown();
            }
        }


    }

    /**
     * 从OSS文件URL中提取ObjectKey
     * 这个方法需要你根据实际URL格式进行调整
     */
    private String extractObjectKeyFromUrl(String url, String endpoint, String bucketName) {
        try {
            // 方法1：如果URL格式是 "https://bucket.endpoint/object-key"
            String bucketEndpointPrefix = "https://" + bucketName + "." + endpoint.replace("https://", "") + "/";
            if (url.startsWith(bucketEndpointPrefix)) {
                return url.substring(bucketEndpointPrefix.length());
            }
            // 如果以上都不匹配，返回null或空字符串
            return null;
        } catch (Exception e) {
            log.error("解析URL时出错: " + url + ", 错误: " + e.getMessage());
            return null;
        }
    }
    public List<String> getUrls(List<String> names) {
        List<String> urls = new ArrayList<>();
        for (String name : names) {
            urls.add("https://" + aliYunOSSProperties.getBucketName() + "." + aliYunOSSProperties.getEndpoint().substring(8) + "/" + name);
        }
        return urls;
    }
}